package panel

import "⚛sdl"
import "⚛sdl/ttf"
// import "⚛sdl/gfx"

type Type interface {
    Key(rune int) Type
    Resize(lines, cols int, lineOffset, colOffset int)
    FocusForClick(line, col int) Type
    Focus()
    Cursor(line, col int)
    Parent(p Type)
    Refresh()
    Put(line, col int, rune int)
    PutString(line, col int, text string)
    Show(message string)
    Box(line, col int, oline, ocol int)
}

type Display struct {
	screen *sdl.Surface
	font *ttf.Font
	fontHeight int
	fontWidth int
}

type WindowPanel struct {
    display *Display
    // win xgb.Id
    // gc xgb.Id
    // gc_xor xgb.Id
    cursorLine, cursorCol int
    // font xgb.Id
    lines, cols int
    body Type
}

func NewWindowPanel(con *sdl.Surface, body Type) *WindowPanel {
	con.FillRect(nil, 0xffffff)	
	font := ttf.OpenFont("/usr/share/fonts/liberation/LiberationMono-Regular.ttf", 12) // "/usr/share/fonts/msttcore/verdanaz.ttf", 12)
	fontHeight := font.LineSkip()
	// int(minx), int(maxx), int(miny), int(maxy), int(advance), int(err)
	_, _, _, _, advance, _ := font.GlyphMetrics('A')
    wp := &WindowPanel{display: &Display{con, font, fontHeight, advance}, body: body}
    body.Parent(wp)
    return wp
}

func (w *WindowPanel) Flip() {
	w.display.screen.Flip()
}

func (w *WindowPanel) Refresh() {
	// func (c *Conn) ClearArea(Exposures bool, Window Id, X int16, Y int16, Width uint16, Height uint16)
	Log("WindowPanel.Refresh")
    // width, height := uint16(w.cols * pixels_per_col), uint16(w.lines * pixels_per_line)
    // w.con.ClearArea(true, w.win, 0, 0, width, height )
    w.display.screen.FillRect(&sdl.Rect{}, 0xffffff)
    w.body.Refresh()
    w.display.screen.Flip()
}

func (w *WindowPanel) Show(message string) {
	Log(message)
}

func (w *WindowPanel) Resize(lines, cols int, lineOffset, colOffset int) {
    w.lines, w.cols = lines, cols
    w.body.Resize(lines, cols, lineOffset, colOffset)
}

func (w *WindowPanel) Focus() {
}

func (w *WindowPanel) Parent(p Type) {
    panic("cannot give a WindowPanel a parent")
}

func (w *WindowPanel) Key(rune int) Type {
    return nil
}

func (w *WindowPanel) FocusForClick(line, col int) Type {
    // return w.body.FocusForClick(line, col)
    return nil
}

func (w *WindowPanel) Put(line, col int, rune int) {
    w.PutString(line, col, string([]byte{byte(rune)}) )
}

func (w *WindowPanel) Box(line, col int, oline, ocol int) {
	// draw a box
	w.line(line, col, oline, col)
	w.line(oline, col, oline, ocol)
	w.line(oline, ocol, line, ocol)
	w.line(line, ocol, line, col)
}

func (w *WindowPanel) Cursor(line, col int) {
	w.cursorLine, w.cursorCol = line, col
}

var saved *sdl.Surface
var saveLine, saveCol int

func (wp *WindowPanel) ShowCursor() {
	var pixels_per_line = wp.display.fontHeight
	if saved == nil {
		saved = sdl.CreateRGBSurface(0, 1, int(pixels_per_line), 32, 0, 0, 0, 0);
	}	
	line, col := wp.cursorLine, wp.cursorCol
	saveLine, saveCol = line, col
	Log("ShowCursor at: line, col = ", line, col)
	var pixels_per_col = wp.display.fontWidth
	x := int16(col * pixels_per_col)
	y := int16(line * pixels_per_line + 2)
	saved.Blit(&sdl.Rect{0, 0, 0, 0}, wp.display.screen,&sdl.Rect{x, y, 1, uint16(pixels_per_line)})  
	wp.display.screen.FillRect(&sdl.Rect{x, y, 1, uint16(pixels_per_line)}, uint32(0))
	wp.display.screen.UpdateRect( int32(x), int32(y), 1, uint32(pixels_per_line) )
}

func (wp *WindowPanel) HideCursor() {
	var pixels_per_line = wp.display.fontHeight
	if saved == nil {
		saved = sdl.CreateRGBSurface(0, 1, int(pixels_per_line), 32, 0, 0, 0, 0);
	}	
	line, col := saveLine, saveCol // wp.cursorLine, wp.cursorCol
	Log("HideCursor from: ", line, col)	
	var pixels_per_col = wp.display.fontWidth
	x := int16(col * pixels_per_col)
	y := int16(line * pixels_per_line + 2)
	wp.display.screen.Blit(&sdl.Rect{x, y, 1, uint16(pixels_per_line)}, saved, nil)
	wp.display.screen.UpdateRect( int32(x), int32(y), 1, uint32(pixels_per_line) )
}

func (w *WindowPanel) line(line, col int, oline, ocol int) {
	if line == oline { w.hline(line, col, ocol - col) }	else { w.vline(line, col, oline - line) }
}

func (wp *WindowPanel) hline(line, col int, width int) {
	if width < 0 { col += width; width = -width }
	var pixels_per_line = wp.display.fontHeight
	var pixels_per_col = wp.display.fontWidth
	// Log("hline: line, col, width = ", line, col, width)
	x := int16(col * pixels_per_col + pixels_per_col/2)
	y := int16(line * pixels_per_line + pixels_per_line/2)
	w := uint16(width * pixels_per_col)
	wp.display.screen.FillRect(&sdl.Rect{x, y, w, 2}, 0xff8080) 
}

func (wp *WindowPanel) vline(line, col int, height int) {
	if height < 0 { line += height; height = -height }
	// Log("vline: line, col, height = ", line, col, height)
	var pixels_per_line = wp.display.fontHeight
	var pixels_per_col = wp.display.fontWidth
	x := int16(col * pixels_per_col + pixels_per_col/2)
	y := int16(line * pixels_per_line + pixels_per_line/2)
	h := uint16(height * pixels_per_line)
	wp.display.screen.FillRect(&sdl.Rect{x, y, 2, h}, 0xff8080) 
}

func (wp *WindowPanel) ResizeInPixels(width, height int) (lines, cols int) {
	var pixels_per_line = wp.display.fontHeight
	var pixels_per_col = wp.display.fontWidth
	lines, cols = height / pixels_per_line, width / pixels_per_col
	Log("ResizeInPixels: lines, cols := ", lines, cols)
	wp.display.screen.Free()
	screen := sdl.SetVideoMode(width + 2, height + 2, 32, sdl.RESIZABLE)
	wp.display.screen = screen	
	screen.FillRect(nil, 0xffffff)	
	wp.Resize(lines, cols, 0, 0)
	return
}

func (wp *WindowPanel) PutString(line, col int, text string) {
	// Log("PutString: '", text, "'")
	font := wp.display.font
	var pixels_per_line = wp.display.fontHeight
	var pixels_per_col = wp.display.fontWidth
	surf := ttf.RenderText_Shaded(font, text, sdl.Color{0, 0, 255, 0}, sdl.Color{255, 255, 255, 255})
	if surf == nil { Log("ARGH - surf == nil for ", text); return  }
	x := int16(col * pixels_per_col)
	y := int16(line * pixels_per_line + 2)
	w := uint16(len(text) * pixels_per_col)
	h := uint16(pixels_per_line)
	where := &sdl.Rect{x, y, w, h}
	wp.display.screen.Blit(where, surf, nil)
	surf.Free()
}
